#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <time.h>
#define ERROR_CHECK(ret, num, msg) \
    {                              \
        if (ret == num)            \
        {                          \
            perror(msg);           \
            exit(1);               \
        }                          \
    }
#define ARGS_CHECK(argc, num)                 \
    {                                         \
        if (argc != num)                      \
        {                                     \
            fprintf(stderr, "args error!\n"); \
            return -1;                        \
        }                                     \
    }
char getFileType(__mode_t mode)
{
    if (S_ISDIR(mode))
        return 'd';
    if (S_ISBLK(mode))
        return 'b';
    if (S_ISCHR(mode))
        return 'c';
    if (S_ISFIFO(mode))
        return 'p';
    if (S_ISLNK(mode))
        return 'l';
    if (S_ISSOCK(mode))
        return 's';
    if (S_ISREG(mode))
        return '-';
    return '?';
}

char *get_permissions(__mode_t mode)
{
    static char permissions[10];
    strcpy(permissions, "rwxrwxrwx");
    permissions[9] = '\0';
    for (size_t i = 0; i < 9; i++)
    {
        if (!(mode & 1 << (8 - i))) // mode &100  ; mode & 010 ; mode & 001;
        {
            permissions[i] = '-';
        }
    }
    
    return permissions;
}
int main(int argc, char *argv[])
{
    ARGS_CHECK(argc,2);
    DIR *dirp = opendir(argv[1]);
    ERROR_CHECK(NULL, dirp, "opendir");
    int ret = chdir(argv[1]);
    struct dirent *dirpStructure;
    struct stat statBuf;
    while (dirpStructure = readdir(dirp))
    {
        int ret = stat(dirpStructure->d_name, &statBuf);
        ERROR_CHECK(-1, ret, "stat");
        char file_type = getFileType(statBuf.st_mode);
        struct passwd * uid = getpwuid(statBuf.st_uid); 
        struct group * gid = getgrgid(statBuf.st_gid);
        char mtime[20];
        strftime(mtime,sizeof(mtime),"%b %d %H:%M",localtime(&statBuf.st_mtime));
        printf("%c%s %2ld %s %s %5ld %s %s\n", file_type,
               get_permissions(statBuf.st_mode),
               statBuf.st_nlink,
                uid->pw_name, 
                gid->gr_name,
                statBuf.st_size,
                mtime,
               dirpStructure->d_name);
    }
    puts("");

    return 0;
}
